﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Common.Helper;
using Common.Constants;
using Common.Interface;
using EntityFrameworkExtension;
using EntityFrameworkExtension.Interface;
using MainProcessor.Interface;

namespace MainProcessor.ContextProcessor
{
    public class ReplacedInteface2Processor : BaseContextProcessor<ReplacedInteface2>, IContextProcessor
    {
        private readonly IDataCache dataCache;
        private readonly IEntityFactory entityFactory;

        public ReplacedInteface2Processor(IDataCache dataCache, IDataController dataController, IEntityFactory entityFactory)
            : base(dataController)
        {
            this.dataCache = dataCache;
            this.entityFactory = entityFactory;
        }

        public void ExtractXml(XElement xElement)
        {
            List = (from iv in xElement.Descendants(XmlConstants.ParentContainer)
                        let mappingId = iv.Element(XmlConstants.MappingId)
                    from ii in entityFactory.CreateChildren(iv)
                        let childGuid = ii.BaseElement.Element(XmlConstants.ChildGuid)
                        let name = ii.BaseElement.Element(XmlConstants.ChildName)
                        let uniqueChildProperty = ii.BaseElement.Element(XmlConstants.UniqueChildProperty1)
                        let commonChildProperty = ii.TopElement.Element(XmlConstants.CommonChildProperty1)
                        where !mappingId.IsNullOrEmpty()
                    select
                        new ReplacedInteface2()
                            {
                                MappingId = NullableValue<int>(mappingId),
                                Name = name.IsNullOrEmpty() ? default(String) : name.Value,
                                ChildGuid = new Guid(childGuid.Value),
                                uniqueChildProperty = NullableValue<bool>(uniqueChildProperty),
                                CommonChildProperty = commonChildProperty.IsNullOrEmpty() ? default(String) : commonChildProperty.Value,
                            })
                            // This is so that there is an object to use to delete all children from the parents when the input XML has no children
                            .Union(from iv in xElement.Descendants(XmlConstants.ParentContainer)
                                     let mappingId = iv.Element(XmlConstants.MappingId)
                                     let ii = entityFactory.CreateChildren(iv)
                                     where ii.Count() == 0 && !mappingId.IsNullOrEmpty()
                                     select new ReplacedInteface2()
                                                {
                                                    MappingId = NullableValue<int>(mappingId),
                                                    ParentGuid = default(Guid)
                                                }
                                         ).ToList();
        }


        public void PopulateEf(IEfContext efContext)
        {
            foreach (var child in List)
            {
                if (child.MappingId != null) child.ParentGuid= GetGuid(child.MappingId.Value);
            }
            UpDelSert(efContext, new FundPriceShareClassComparer(), x => x.ParentGuid, GetExisting);
        }

        private static IEnumerable<ReplacedInteface2> GetExisting(Guid inputGuid, IEfContext efContext)
        {
            return efContext.GetObjectList<ReplacedInteface2>(y => y.ParentGuid == inputGuid);
        }


        private class FundPriceShareClassComparer : IEqualityComparer<ReplacedInteface2>
        {
            public bool Equals(ReplacedInteface2 x, ReplacedInteface2 y)
            {
                return x.ChildGuid == y.ChildGuid;
            }

            public int GetHashCode(ReplacedInteface2 obj)
            {
                return obj.ChildGuid.GetHashCode();
            }
        }
    }
}
